﻿using System;
using System.Collections.Generic;
using System.Windows.Controls;

namespace AgLux
{
    /// <summary>
    /// Represents a canvas that displays a list of Answer objects associated with a specific question.
    /// </summary>

    public class Question : Canvas
    {
        public event EventHandler AnswerMarked;
        public event EventHandler AnswerUnmarked;

        private string _text;
        private List<Answer> _answers;
        private bool _isAnswered, _isCorrected;

        private static int _shuffles = 0;

        /// <summary>
        /// Initializes a new instance of the Question class.
        /// </summary>

        /// <param name="text">
        /// The question text.
        /// </param>

        /// <param name="answers">
        /// The list of choosable Answer objects.
        /// </param>

        public Question(string text, List<Answer> answers)
            : base()
        {
            _text = text;
            _answers = answers;
            _isAnswered = _isCorrected = false;

            ShuffleAnswers();
            foreach (Answer answer in _answers)
            {
                answer.Marked += new EventHandler(UnmarkAnswers);
                answer.Unmarked += new EventHandler(UnmarkAnswer);
                Children.Add(answer);
            }
        }

        /// <summary>
        /// Gets the question text.
        /// </summary>

        public string Text
        {
            get
            {
                return _text;
            }
        }

        /// <summary>
        /// Gets whether an answer is chosen.
        /// </summary>

        public bool IsAnswered
        {
            get
            {
                return _isAnswered;
            }
        }

        /// <summary>
        /// Gets whether the question is corrected.
        /// </summary>

        public bool IsCorrected
        {
            get
            {
                return _isCorrected;
            }
        }

        /// <summary>
        /// Prepare to display the canvas.
        /// </summary>

        /// <param name="width">
        /// The width of the canvas on which the canvas will be displayed.
        /// </param>

        public void Prepare(double width)
        {
            Width = width;
            Height = 0;

            foreach (Answer answer in _answers)
            {
                answer.Prepare(Width);
                answer.SetValue(Canvas.TopProperty, Height);
                Height += answer.Height;
            }
        }

        /// <summary>
        /// Corrects the question.
        /// </summary>

        /// <returns>
        /// The number of points.
        /// </returns>

        public int Correct()
        {
            int points = 0;

            if (_isAnswered)
            {
                _isCorrected = true;
                foreach (Answer answer in _answers)
                {
                    if (answer.Correct())
                    {
                        points++;
                    }
                }
            }

            return points;
        }

        /// <summary>
        /// Shuffles the answers.
        /// </summary>

        private void ShuffleAnswers()
        {
            if (_answers.Count > 1)
            {
                List<Answer> answers = new List<Answer>();
                Random random = new Random(_shuffles + DateTime.Now.Millisecond);
                int index = random.Next(_answers.Count);

                while (_answers.Count > 0)
                {
                    answers.Add(_answers[index]);
                    _answers.RemoveAt(index);
                    index = random.Next(_answers.Count);
                }

                _answers = answers;
                _shuffles++;
            }
        }

        /// <summary>
        /// Occurs when an answer is marked.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void UnmarkAnswers(object sender, EventArgs args)
        {
            _isAnswered = true;
            Answer markedAnswer = (Answer)sender;
            foreach (Answer answer in _answers)
            {
                if (answer != markedAnswer)
                {
                    answer.Unmark();
                }
            }
            OnAnswerMarked(new EventArgs());
        }

        /// <summary>
        /// Occurs when an answer is unmarked.
        /// </summary>

        /// <param name="sender">
        /// The object that raised the event.
        /// </param>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void UnmarkAnswer(object sender, EventArgs args)
        {
            _isAnswered = false;
            OnAnswerUnmarked(new EventArgs());
        }

        /// <summary>
        /// Raises the AnswerMarked event.
        /// </summary>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void OnAnswerMarked(EventArgs args)
        {
            if (AnswerMarked != null)
            {
                AnswerMarked(this, args);
            }
        }

        /// <summary>
        /// Raises the AnswerUnmarked event.
        /// </summary>

        /// <param name="args">
        /// The EventArgs that contains the event data.
        /// </param>

        private void OnAnswerUnmarked(EventArgs args)
        {
            if (AnswerUnmarked != null)
            {
                AnswerUnmarked(this, args);
            }
        }
    }
}
